﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;

using System.IO;
using System.Linq;

using ProjectBase.Core;
using ProjectBase.Mvc;

using $prjsn$.Common.Business;
using $prjsn$.Common.Business.Services;
using $prjsn$.Common.Data.Services;
using $prjsn$.Common.Validation;
using $prjsn$.Entity.Services;

namespace $safeprojectname$.Services
{
    /// <summary>
    ///     All Business checks for 'Attachment' on CRUD operations
    ///     are nested and encapsulated in this AttachmentFacade
    /// </summary>
    public class AttachmentFacade : Facade, IAttachmentFacade
    {
        #region members
        /// <summary>
        ///     Not more then 100 KB
        /// </summary>
        const int MaxImageSize = 100000;

        /// <summary>
        ///     Not more then 10 MB
        /// </summary>
        const int MaxZipSize = 10000000;
        AttachmentValidator _validator;
        #endregion members

        #region PROTOTYPE
        /// <summary>
        ///     Prototype design pattern - in practice.
        ///     The central and only point for creating new entity of type Attachment (prototype).
        ///     Returns new transient entity 'Attachment'
        ///     - some Properties are preset to business defaults.
        ///     (Business rules therefore should be easier to meet)
        /// </summary>
        /// <returns>new entity 'Attachment' transient</returns>
        public virtual Attachment CreateNew()
        {
            return CreateNew(null, null, null, null);
        }

        public virtual Attachment CreateNew(string fileName, string contentType, Stream inputStream, Article article)
        {
            var name = fileName.Split('\\').Last();
            var suffix = "." + name.Split('.').Last();
            var entity = new Attachment
            {
                Name = name,
                ContentType = ContentTypeFacade.GetBySuffix(suffix) ?? ContentTypeFacade.CreateNew("NotFound"),
                Article = article,
                InputStream = inputStream,
            };
            return entity;
        }
        #endregion PROTOTYPE

        #region IAttachmentFacade
        public virtual IEnumerable<Attachment> GetByArticle(Article article)
        {
            var list = Dao.GetByArticle(article);
            foreach (var attachment in list)
            {
                attachment.ContentType = ContentTypeFacade.GetBySuffix(attachment.Suffix);
            }
            return list;
        }

        public virtual Attachment GetByName(string fileName, Article article)
        {
            var entity = Dao.GetByName(fileName, article);
            if (entity.Is())
            {
                entity.ContentType = ContentTypeFacade.GetBySuffix(entity.Suffix);
                return entity;
            }
            return null;
        }

        public virtual Attachment AddOrUpdate(Attachment entity)
        {
            if (Validator.Validate(entity, ValidateOn.Update, this))
            {
                return Dao.AddOrUpdate(entity);
            }
            return entity;
        }

        public virtual void Delete(Attachment entity)
        {
            if (Validator.Validate(entity, ValidateOn.Delete, this))
            {
                Dao.Delete(entity);
            }
        }

        public virtual void ClearAttachments(Article article)
        {
            Dao.ClearAttachments(article);
        }
        #endregion IAttachmentFacade

        #region ValidationRules
        public virtual bool CheckContentType(Attachment entity)
        {
            if (entity.ContentType.IsImage
                || entity.ContentType.IsZip)
            {
                return true;
            }
            this.PublishError("ProvidedFileWasOfProhibitedContentType {0} {1}",
                entity.Name, entity.InputStream.Length);
            return false;
        }

        public virtual bool CheckInputStreamLength(Attachment entity)
        {
            var size = entity.InputStream.Length;

            if (entity.ContentType.IsImage
                && size > MaxImageSize)
            {
                this.PublishError("ProvidedFileWasToLarge {0} {1}"
                    , size
                    , MaxImageSize);
                return false;
            }
            if (entity.ContentType.IsZip
                && size > MaxZipSize)
            {
                this.PublishError("ProvidedFileWasToLarge {0} {1}"
                    , size
                    , MaxZipSize);
                return false;
            }

            return true;
        }
        #endregion ValidationRules

        #region properties
        public virtual AttachmentValidator Validator
        {
            get
            {
                if (_validator.IsNull())
                {
                    _validator = new AttachmentValidator();
                }
                return _validator;
            }
            set { _validator = value; }
        }

        public virtual IContentTypeFacade ContentTypeFacade { protected get; set; }
        public virtual IAttachmentDao Dao { protected get; set; }
        #endregion properties
    }
}